using System;
using System.Drawing;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;
using WeifenLuo.WinFormsUI.Docking;
using System.Text.RegularExpressions;

namespace TestPlugin
{
    public partial class CommandPrompt : DockContent
    {
        public delegate void UpdateOutputCallback(string text);
        private StreamWriter _writer;
        private bool _command = false;

        private Process mainCommandProcess;

        public CommandPrompt()
        {
            InitializeComponent();

            rtbOutput.GotFocus += rtbOutput_GotFocus;
        }

        void rtbOutput_GotFocus(object sender, EventArgs e)
        {
            cmbInput.Focus();
        }

        void CommandPrompt_Load(object sender, EventArgs e)
        {
            StartCommandPrompt();
            cmbInput.Focus();
        }

        private void cmbInput_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                RunCommand(cmbInput.Text);
            }
        }

        private void StartCommandPrompt()
        {
            var cmd = mainCommandProcess = new Process();
            cmd.StartInfo.FileName = "cmd.exe";
            cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            cmd.StartInfo.CreateNoWindow = true;
            cmd.StartInfo.UseShellExecute = false;
            cmd.StartInfo.RedirectStandardError = true;
            cmd.StartInfo.RedirectStandardInput = true;
            cmd.StartInfo.RedirectStandardOutput = true;

            cmd.OutputDataReceived += HandleOutput;
            cmd.ErrorDataReceived += HandleError;

            cmd.Start();
            _writer = cmd.StandardInput;
            _writer.WriteLine("cd " + Path.GetDirectoryName(Application.ExecutablePath));
            
            cmd.BeginErrorReadLine();
            cmd.BeginOutputReadLine();
        }

        void HandleError(object sender, DataReceivedEventArgs e)
        {
            if (!string.IsNullOrEmpty(e.Data))
            {
                rtbOutput.Invoke(new UpdateOutputCallback(UpdateError), new object[] { e.Data });
            }
        }

        void HandleOutput(object sender, DataReceivedEventArgs e)
        {
            if (!string.IsNullOrEmpty(e.Data))
            {
                rtbOutput.Invoke(new UpdateOutputCallback(UpdateOutput), new object[] { e.Data });
            }
        }

        private void UpdateOutput(string text)
        {
            if (!_command && text.IndexOf(">cd") == text.Length - 3)
            {
                return;
            }

            int start = rtbOutput.TextLength;

            rtbOutput.AppendText(text + System.Environment.NewLine);

            if (_command)
            {
                rtbOutput.Select(start, text.Length);
                rtbOutput.SelectionColor = Color.Yellow;
                rtbOutput.Select(rtbOutput.TextLength, 0);
                _command = false;
            }

            rtbOutput.ScrollToCaret();
        }

        private void UpdateError(string text)
        {
            int start = rtbOutput.TextLength;
            rtbOutput.AppendText(text + System.Environment.NewLine);
            rtbOutput.Select(start, text.Length);
            rtbOutput.SelectionColor = Color.Red;
            rtbOutput.Select(rtbOutput.TextLength, 0);
            rtbOutput.ScrollToCaret();
        }

        /*public void RunScript(string script, string workingDirectory)
        {
            int index = workingDirectory.IndexOf(":\\");
            if (index > 0)
            {
                this._writer.WriteLine(workingDirectory.Substring(0, index + 1));
            }
            this._writer.WriteLine("cd " + workingDirectory);
            string[] commands = Regex.Split(script, System.Environment.NewLine);
            foreach (string command in commands)
            {
                if (!string.IsNullOrEmpty(command))
                {
                    this._writer.WriteLine(command);
                }
            }
        }*/

        public void RunCommand(string command)
        {
            _writer.WriteLine(command);
            _command = true;
            if (!cmbInput.Items.Contains(command))
            {
                cmbInput.Items.Add(command);
            }
            cmbInput.Text = "";
            _writer.WriteLine("cd");
        }
    }
}
